package com.cjj.common.framework.advice;

import cn.hutool.core.exceptions.ValidateException;
import com.cjj.common.consts.ResConst;
import com.cjj.common.entity.Res;
import com.cjj.common.framework.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;
import com.cjj.common.framework.exception.SecurityException;
import javax.servlet.http.HttpServletRequest;
import java.util.stream.Collectors;


/**
 * @author DoyuTu
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionAdvice {

    @Autowired
    private HttpServletRequest request;

    @ExceptionHandler(Exception.class)
    public Res<String> exceptionHandler(Exception ex) {
        if (ex instanceof BadSqlGrammarException) {
            BadSqlGrammarException e = (BadSqlGrammarException) ex;
            log.error("SQL异常", e);
            return Res.fail(ResConst.BUSINESS_ERROR);
        }
//        if (ex instanceof NoPermissionOperateException) {
//            NoPermissionOperateException e = (NoPermissionOperateException) ex;
//            return Res.fail(e.getMessage());
//        }
//        if (ex instanceof KaptchaException) {
//            String message;
//            if (ex instanceof KaptchaIncorrectException) {
//                message = "验证码不正确";
//            } else if (ex instanceof KaptchaNotFoundException) {
//                message = "验证码未找到";
//            } else if (ex instanceof KaptchaTimeoutException) {
//                message = "验证码过期";
//            } else {
//                message = "验证码渲染失败";
//            }
//            return Res.fail(message);
//        }
//        if (ex instanceof UserNotFoundException) {
//            return Res.fail("用户不存在");
//        }
        if (ex instanceof BusinessException) {
            BusinessException e = (BusinessException) ex;
            log.info("业务异常 ", e);
            return Res.fail(e.getMessage());
        }
//        if (ex instanceof MonitorException) {
//            MonitorException e = (MonitorException) ex;
//            if (StringUtils.equals("暂无权限", e.getMessage())) {
//                return Res.fail(ResConst.FORBIDDEN_ERROR);
//            }
//            return Res.fail(e.getMessage());
//        }
//        if (ex instanceof InsufficientCountException) {
//            if (ex.getMessage() == null) {
//                return Res.fail(ResConst.INSUFFICIENT_ERROR);
//            }
//            return Res.fail(ResConst.INSUFFICIENT_ERROR, ex.getMessage());
//        }
        if (ex instanceof ValidateException) {
            ValidateException e = (ValidateException) ex;
            String message = e.getMessage();
            return Res.fail(message);
        }
        if (ex instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException e = (MethodArgumentNotValidException) ex;
            return Res.fail(ResConst.PARAMETER_ERROR, e.getBindingResult()
                    .getFieldErrors().stream().map(t -> t.getField() + t.getDefaultMessage())
                    .collect(Collectors.joining(", ")));
        }
        if (ex instanceof MissingServletRequestParameterException) {
            MissingServletRequestParameterException e = (MissingServletRequestParameterException) ex;
            return Res.fail(ResConst.BAD_REQUEST, String.format("Missing must request parameter：%s", e.getParameterName()));
        }
        if (ex instanceof BindException) {
            BindException e = (BindException) ex;
//            return Res.fail(ResConst.BAD_REQUEST, "Reject request parameters " + e.getFieldErrors()
//                    .stream()
//                    .map(fieldError -> String.format("[%s：%s]", fieldError.getField(), fieldError.getRejectedValue()))
//                    .collect(Collectors.joining(",")));
            return Res.fail(ResConst.BAD_REQUEST, e.getFieldErrors()
                    .stream()
                    .map(DefaultMessageSourceResolvable::getDefaultMessage)
                    .collect(Collectors.joining(",")));
        }
        if (ex instanceof HttpMessageNotReadableException) {
            log.error("HTTP消息格式有误", ex);
            return Res.fail(ResConst.SYSTEM_ERROR);
        }
        if (ex instanceof NoHandlerFoundException || ex instanceof HttpMediaTypeNotAcceptableException || ex instanceof HttpMediaTypeNotSupportedException) {
            log.error("不能处理异常", ex);
            return Res.fail(ex.getMessage());
        }
        if (ex instanceof IllegalArgumentException || ex instanceof MethodArgumentTypeMismatchException || ex instanceof ConversionFailedException || ex instanceof IllegalStateException) {
            log.error("参数转换异常", ex);
            return Res.fail(ResConst.PARAMETER_ERROR);
        }
        if (ex instanceof HttpRequestMethodNotSupportedException) {
            return Res.fail(ResConst.METHOD_NOT_ALLOWED);
        }
        if (ex instanceof SecurityException) {
            SecurityException e = (SecurityException) ex;
            return Res.fail(e);
        }
        if (ex instanceof RuntimeException) {
            log.error("运行异常", ex);
            return Res.fail(ResConst.BUSINESS_ERROR);
        }
        //default
        log.error("defaultExceptionHandler URL：{}", request.getRequestURI(), ex);
        return Res.fail(ResConst.SYSTEM_ERROR);
    }

}
